//
//  MCNetworking.h
//  iMooc
//
//  Created by CoderXSLee on 13/5/3.
//  Copyright © 2013年 李雪松. All rights reserved.
//

#import "MCResponseTool.h"
#import "MCAnalyzedResult.h"
#import "MCNetworkMonitoring.h"

#if __has_include(<AFNetworking/AFSecurityPolicy.h>)
#import <AFNetworking/AFSecurityPolicy.h>
#elif __has_include("AFSecurityPolicy.h")
#import "AFSecurityPolicy.h"
#endif

#if __has_include(<AFNetworking/AFURLRequestSerialization.h>)
#import <AFNetworking/AFURLRequestSerialization.h>
#elif __has_include("AFURLRequestSerialization.h")
#import "AFURLRequestSerialization.h"
#endif


/// 需要面向用户的结果码的范围 如：20001 ～ 29999 之间的code 需要提示用户 msg
struct MCResultCodeDigitalRange {
    NSInteger startNumber; /// 面向用户的开始值(最小值)
    NSInteger endNumber; /// 面向用户的结束值(最大值)
};
typedef struct CG_BOXABLE MCResultCodeDigitalRange MCResultCodeDigitalRange;

CG_INLINE struct MCResultCodeDigitalRange MCResultCodeDigitalRangeMake(NSInteger startNumber, NSInteger endNumber);

CG_INLINE MCResultCodeDigitalRange MCResultCodeDigitalRangeMake(NSInteger startNumber, NSInteger endNumber)
{
    MCResultCodeDigitalRange range; range.startNumber = startNumber; range.endNumber = endNumber; return range;
}

/// 网络请求的回调
typedef void (^NetworkBlock) (MCCommonResult *result, id responseObject);

@interface MCNetworking : NSObject

/// 获取baseURL ，该值在 setBaseURLString: 中修改
@property (strong, nonatomic, readonly) NSString *baseURL;

/// 获取HTTPRequestHeaders ，该值在 setHeaderValue: 中修改
@property (strong, nonatomic, readonly) NSDictionary *HTTPRequestHeaders;

/// 服务器返回的 responseObject 中的 key ，该值在 setResponseObjectCodeKey:msgKey:dataKey: 中修改
@property (strong, nonatomic, readonly) NSDictionary *responseObjectKeys;

/// 需要面向用户的结果码 【如：20001 ～ 29999 之间的code 需要提示用户 msg】
@property (assign, nonatomic, readonly) MCResultCodeDigitalRange codeRange;

/// 设置为NO后，添加网络代理时，将不会发送网络请求
@property (nonatomic, assign, readonly) BOOL available;

/// 在请求前，当parameter为nil时，是否自动替换为空字典@{}，该值请在 setEmptyParameIsReplaceEmptyDictionary: 中设置
@property (nonatomic, assign, readonly) BOOL isRepaceParame;

/// 取消所有正在进行的网络请求
+ (void)cancelAllRequest;

/// 根据url取消正在进行的网络请求
+ (void)cancelNetworkingWithUrlString:(NSString *)url;

/// GET 请求 例如: www.baidu.com/getUserAddressList/1207 (1207为UID)
+ (void)GET:(NSString *)urlString networkBlock:(NetworkBlock)networkBlock;

/// GET 请求 适用于 REST URI 例如: www.baidu.com/getUserAddressList/?userID=1207
+ (void)GET:(NSString *)urlString parameters:(NSDictionary *)parameters networkBlock:(NetworkBlock)networkBlock;

/// POST 请求
+ (void)POST:(NSString *)urlString parameters:(NSDictionary *)parameters networkBlock:(NetworkBlock)networkBlock;

/// 上传文件post请求
+ (void)POST:(NSString *)urlString parameters:(NSDictionary *)parameters data:(NSData *)data name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType networkBlock:(NetworkBlock)networkBlock;

/// 上传多张图片 POST请求
+ (void)POST:(NSString *)urlString parameters:(NSDictionary *)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block fileName:(NSString *)fileName progress:(void(^)(NSProgress *uploadProgress))uploadProgressBlock networkBlock:(NetworkBlock)networkBlock;

/// PUT 请求
+ (void)PUT:(NSString *)urlString parameters:(NSDictionary *)parameter networkBlock:(NetworkBlock)networkBlock;

/// DELETE 请求
+ (void)DELETE:(NSString *)urlString parameters:(NSDictionary *)parameters networkBlock:(NetworkBlock)networkBlock;

/// 设置为NO后，添加网络代理时，将不会发送网络请求
- (void)setNetworkProxyAvailable:(BOOL)available;

/// https  请求第一步，下载Cer证书
+ (void)requestCertWithUrl:(NSString *)url completion:(void (^)(BOOL result))completion;

/// 设置baseURL 如果baseURL有值，每次请求会在url前拼接此baseURL
- (void)setBaseURLString:(NSString *)urlString;

/*  设置安全策略
     先导入证书 证书由服务端生成，具体由服务端人员操作
     NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"keystore" ofType:@"cer"]; //证书的路径 xx.cer
     NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
     AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
     假如证书的域名与你请求的域名不一致，需把该项设置为NO；如设成NO的话，即服务器使用其他可信任机构颁发的证书，也可以建立连接，这个非常危险，建议打开。
     置为NO，主要用于这种情况：客户端请求的是子域名，而证书上的是另外一个域名。因为SSL证书上的域名是独立的，假如证书上注册的域名是www.google.com，那么mail.google.com是无法验证通过的；当然，有钱可以注册通配符的域名*.google.com，但这个还是比较贵的。
     如置为NO，建议自己添加对应域名的校验逻辑。
     AFSSLPinningModeCertificate 使用证书验证模式
     allowInvalidCertificates 是否允许无效证书（也就是自建的证书），默认为NO
     如果是需要验证自建证书，需要设置为YES
     securityPolicy.allowInvalidCertificates = YES;
    validatesDomainName 是否需要验证域名，默认为YES;
 */
- (void)setSecurityPolicy:(AFSecurityPolicy *)securityPolicy;

/// 设置请求超时时间，默认 30 秒
- (void)setTimeoutInterval:(NSInteger)TimeoutInterval;

/// 在请求头中添加KeyValue 每次请求都会携带该值
- (void)setHeaderValue:(NSString *)value forKey:(NSString *)key;

/// 在所有的POST请求中，当parameter为nil时，是否自动替换为空字典@{}
- (void)setEmptyParameIsReplaceEmptyDictionary:(BOOL)replace;

/**
 可以自定义 AcceptableContentTypes
 默认：[application/json，text/json，text/html，text/css，text/javascript]
*/
- (void)AcceptableContentTypes:(NSSet *)acceptableContentTypes;

/**
 解析服务器返回的 responseObject 中用到的 key
 假设服务器返回的字典如 { code:20000, message:success, data:{} }
 则codeKey为code，responseMessageKeyString为message，responseDataKeyString为data
 
@param codeKey 为返回字典中的code
@param msgKey 为Response中的message
@param dataKey 为Response中的数据data
*/
- (void)setResponseObjectCodeKey:(NSString *)codeKey msgKey:(NSString *)msgKey dataKey:(NSString *)dataKey;

/// 需要面向用户的结果码 如：20001 ～ 29999 之间的code 需要将message提示用户
- (void)setMCResultCodeDigitalRange:()range;MCResultCodeDigitalRange

/// 添加请求的基础参数，在每次请求都会携带改参数
- (void)addParameterValue:(id)value forKey:(NSString *)key NS_DEPRECATED(3_0, 3_0, 3_3, 3_3, "已弃用-lxs");

@end


/// 单例
@interface MCNetworking (Singleton)
+ (instancetype)sharedInstance;
@end
